#include"zoo.h"

//------------some function to use--------------
string get_rand_name()
{
	string s;
	s =s+ char(rand() % 26 + 'A');
	for(int i=0;i<4;++i)
	s = s + char(rand() % 26 + 'a');
	return s;
}

double get_pass_id()
{
	return double(rand() % 100000);
}

double get_adult_age()
{
	return double(rand() % 80 + 18);
}

double get_child_age()
{
	return double(rand() % 18);
}

//----------------------money class----------------
const Money Money::operator +(const Money & i) const
{
	Money k;
	if (i.m >= 0)
	{
		k.m = this->m + i.m;
		return k;
	}
	else cerr << "The money should over 0.";
	return k;
};
const Money  Money::operator -(const Money & i) const
{
	Money k;
	if (this->m >= i.m)
	{
		k.m = this->m - i.m;
		return k;
	}
	else cerr << "The minuend money should greater than subtrator.";
	return k;
};
const Money  Money::operator +=(const Money & i) const
{
	Money k;
	if (i.m >= 0)
	{
		k.m = this->m + i.m;
		return k;
	}
	else cerr << "The money should over 0.";
	return k;
};
const Money  Money::operator -=(const Money & i) const
{
	Money k;
	if (this->m >= i.m)
	{
		k.m = this->m - i.m;
		return k;
	}
	else cerr << "The minuend money should greater than subtrator.";
	return k;
};
const Money  Money::operator*(const Money &i) const
{
	Money k;
	if (i.m > 0)
	{
		k.m = this->m*i.m;
		return k;
	}
	else cerr << "The money should greater than 0.";
	return k;
};
const Money  Money::operator*=(const Money &i) const
{
	Money k;
	if (i.m > 0)
	{
		k.m = this->m*i.m;
		return k;
	}
	else cerr << "The money should greater than 0.";
	return k;
};


//--------------------Elephant class-------------------
Elephant::Elephant()
{
	trunk_length = 0;
	enclosure.dirtlevel = 0;
	enclosure.status = 1;
}
Elephant::Elephant(double i)
{
	setAnimal(0, 750,"peanuts");
	enclosure.dirtlevel = 0;
	enclosure.status = 1;
	trunk_length = i;
}
Elephant::~Elephant() {};
void Elephant::eatfood(double i) 
{
	addfood(i);
	enclosure.dirtlevel += i;
};
double Elephant::return_dirtlevel() 
{ 
	return enclosure.dirtlevel; 
};

void Elephant::setstatus(bool k)
{
	enclosure.status = k;
}

bool Elephant::getstatus()
{
	return enclosure.status;
}
void Elephant::reset_dirty()
{
	enclosure.dirtlevel = 0;
}
//-------------Giraffe class-------------------
Giraffe::Giraffe()
{
	neck_length = 0;
	enclosure.dirtlevel = 0;
	enclosure.status = 1;

}
Giraffe::Giraffe(double i)
{
	setAnimal(0,500, "carrots");
	enclosure.dirtlevel = 0;
	enclosure.status = 1;
	neck_length = i;
}
Giraffe::~Giraffe() {};
void Giraffe::eatfood(double i) 
{
	addfood(i); 
	enclosure.dirtlevel +=i ;
};
double Giraffe::return_dirtlevel()
{ 
	return enclosure.dirtlevel;
};
void Giraffe::setstatus(bool k)
{
	enclosure.status = k;
}
bool Giraffe::getstatus()
{
	return enclosure.status;
}
void Giraffe::reset_dirty()
{
	enclosure.dirtlevel = 0;
}
//-------------------------Monkey class-----------------
Monkey::Monkey()
{
	arm_length = 0;
	enclosure.dirtlevel = 0;
	enclosure.status = 1;

}
Monkey::Monkey(double i)
{
	setAnimal(0,300, "bananas");
	enclosure.dirtlevel = 0;
	enclosure.status = 1;
	arm_length = i;
}
Monkey::~Monkey() {};
void Monkey::eatfood(double i) 
{
	addfood(i);
	enclosure.dirtlevel += i;
};
double Monkey::return_dirtlevel() 
{ 
	return enclosure.dirtlevel; 
};
void Monkey::setstatus(bool k)
{
	enclosure.status = k;
}
bool Monkey::getstatus()
{
	return enclosure.status;
}
void Monkey::reset_dirty()
{
	enclosure.dirtlevel = 0;
}
//------------Zookeeper----------------
ZooKeeper::ZooKeeper()
{
	cleaning_days = 0;
};
void ZooKeeper::setZooKeeper(string i, double j)
{
	setperson(i, j);
	return;
};
ZooKeeper::~ZooKeeper()
{
};

void ZooKeeper::addcleaning_day()
{
	cleaning_days += 1;
	return;
};
double ZooKeeper::return_cleaningdays()
{
	return cleaning_days;
}

//---------------FoodSeller--------------
FoodSeller::FoodSeller()
{
	amount_monye = 0;
	for (int i = 0; i < 3; i++) closefor[i] = 0;
	return;
};
void FoodSeller::setFoodSeller(string i, double k)
{
	setperson(i, k);
	return;
};
FoodSeller::~FoodSeller() {};
bool FoodSeller::sellfood(string j, double k)
{
	for (int i = 0; i < 3; ++i)
	{
		if (foodkind[i] == j)
			if(foodamout[i]>=k)
		{
			foodamout[i] -= k;
			amount_monye += k*foodprice[i];
			break;
		}
			else
			{
				closefor[i] = 1;
				return false;
			}
	}
	return true;
};

double FoodSeller::getfood_amount(string j)
{
	for (int i = 0; i < 3; i++)
	{
		if (foodkind[i] == j)
			return foodamout[i];
	}
	return 0;
}

double FoodSeller::getfood_price(string j)
{
	for (int i = 0; i < 3; i++)
	{
		if (foodkind[i] == j)
			return foodprice[i];
	}
	return 0;
}

void FoodSeller::selltickets(int k, int l)
{
	amount_monye += (k * 1 + l*0.4);
}
double FoodSeller::return_money()
{
	return amount_monye;
}
//--------------Visitor class----------------
Visitor::Visitor()
{
	pass_id = 0;
};
void Visitor::setVisitor(string i, double k, double l)
{
	setperson(i, k);
	pass_id = l;
};
Visitor::~Visitor() {};

//----------------------Child class--------------
Child::Child()
{
	for (int i = 0; i < 3; ++i)
	{
		food[i].amount = 0;
		food[i].foodtype = "\0";
	}
};
void Child::setChild(string j, double k, double l)
{
	setVisitor(j, k, l);
	return;
};
Child::~Child() {};
void Child::get_animal_food(int j, double k,string l)
{

	food[j].amount = k;
	food[j].foodtype = l;
	return;
};
void Child::feed_food(Animal &i)
{
	if (i.getstatus()==1)
	for (int j = 0; j < 3; ++j)
		if(food[j].foodtype==i.return_foodkind())
		if(food[j].amount>0)
	{
		if (i.getweight() + food[j].amount <= i.getlimit())
		{
			i.eatfood(food[j].amount);
			food[j].amount = 0;
		}
		else
		{
			double k;
				k = (i.getlimit() - i.getweight());
			i.eatfood(k);
			food[j].amount -= k;
		}
	}
};

//--------------------Adult class---------------
Adult::Adult()
{
	money = 0;
	child_number = 0;
	for (int i = 0; i < 3; ++i)
	{
		food[i].amount = 0;
		food[i].foodtype = "\0";
	}
};
Adult::~Adult() { delete[] child; };
void Adult::setadult(double i, double j)
{
	money = i;
	child_number = j;
	int k = int(j);
	child = new Child[k];
};
void Adult::setchild(string i, double j, double k,int kk)
{
	child[kk].setChild(i, j, k);
	return;
};
void Adult::buy_animalfood(FoodSeller & i)
{

	double money_div = money / 3;
	string s[3];
	s[0] = "peanuts"; s[1] = "carrots"; s[2] = "bananas";
	for (int j = 0; j< 3; ++j)
	{
		double amount = i.getfood_amount(s[j]);
		double price = i.getfood_price(s[j]);
	//	cout << price << " " << s[j] << " " << amount << endl;
		if (amount >= money_div / price)
		{
			//cout << 1 << endl;
			i.sellfood(s[j], money / price);
			//cout << 2 << endl;
			money -= money_div;
			food[j].amount = money / price;
			food[j].foodtype = s[j];
		}
		else
		{
			// << 1 << endl;
			if (amount > 0)
			{
			//	cout << 2 << endl;
				money -= price*amount;
				i.sellfood(s[j], amount);
				food[j].amount = amount;
				food[j].foodtype = s[j];
			}
		}
	}
	return;
};

void Adult::distribute()
{
	for (int i = 0; i < child_number; ++i)
	{
		for(int j=0;j<3;++j)
		child[i].get_animal_food(j, food[j].amount / 3, food[j].foodtype);
    }
}

void Adult::fed_animals(Animal & k)
{
	for (int i = 0; i < child_number; ++i)
	{
		child[i].feed_food(k);
	}
}

//--------------------------Zoo class----------------------
Zoo::Zoo()
{
	 dayly_adult=0;
	 dayly_child=0;
	 total_adult=0;
	 total_child=0;
	 total_visitors=0;
	 total_days=0;
	 on_day = 0;
	 for (int i = 0; i < 6; ++i)
	 {
		 closeday[i] = rand() % 3;
	 }
};

Zoo::~Zoo() {};

void Zoo::setzoo_newday(int day, int num)
{
	dayly_adult = num;
	dayly_child = 0;
	adult = new Adult[num];
	for (int i = 0; i < num; i++)
	{
		int numberchild = rand() % 3+ 1;
		dayly_child += numberchild;
		double money = double(rand() % 11 + 10);
		adult[i].setadult(money, numberchild);
		for (int j = 0; j < numberchild; ++j)
		adult[i].setchild(get_rand_name(), get_child_age(), get_pass_id(), j);
	}
	on_day = day;
	total_adult += num;
	total_child += dayly_child;
	total_visitors += total_adult + total_child;
	return;
};
void Zoo::buytickets()
{
	seller.selltickets(dayly_adult, dayly_child);
	return;
};
void Zoo::buyfood()
{
//	cout << dayly_adult << endl;  //---------------
	for (int i = 0; i < dayly_adult; i++)
	{
	//	cout << i << endl;
		adult[i].buy_animalfood(seller);
	//	cout << 0 << endl;
		adult[i].distribute();
	//	cout << 1 << endl;
	}
	return;
};
void Zoo::fed_food()
{
	for (int i = 0; i < dayly_adult; i++)
	{
		adult[i].fed_animals(elephant);
		for(int j=0;j<2;++j)
		adult[i].fed_animals(giraffe[j]);
		for (int j = 0; j<3; ++j)
		adult[i].fed_animals(monkey[j]);
	}
	return;
};
void  Zoo::show_days_open()
{
	cout << "The zoo has opened " << on_day << " days." << endl;
};
void Zoo::show_totnumber()
{
	cout << "During the " << on_day << " days ," << " there are " << total_visitors << " visitors. " << endl;
};
int Zoo::check_close()
{
	if (elephant.getstatus()==0)
	{
		elephant.setstatus(1);
	}
	for (int i = 0; i < 2; i++)
	{
		if (giraffe[i].getstatus() ==0)
		{
			giraffe[i].setstatus(1);
		}
	}
	for (int i = 0; i < 3; i++)
	{
		if (monkey[i].getstatus()==0)
		{
			monkey[i].setstatus(1);
		}
	}
	if (keeper.return_cleaningdays() > 10) return 1;
	if (seller.getfood_amount("peanuts") <= 0) return 2;
	if (seller.getfood_amount("carrots") <= 0) return 3;
	if (seller.getfood_amount("bananas") <= 0) return 4;
	return 0;
};

void Zoo::check_animal_dirty()
{   
	if (elephant.return_dirtlevel() > 2000)
	{
		elephant.setstatus(0);
		keeper.addcleaning_day();
		elephant.reset_dirty();
	}
	for (int i = 0; i < 2; i++)
	{
		if (giraffe[i].return_dirtlevel() > 2000)
		{
			giraffe[i].setstatus(0);
			keeper.addcleaning_day();
			giraffe[i].reset_dirty();
		}
	}
	for (int i = 0; i < 3; i++)
	{
		if (monkey[i].return_dirtlevel() > 2000)
		{
			monkey[i].setstatus(0);
			keeper.addcleaning_day();
			monkey[i].reset_dirty();
		}
	}
}

void Zoo::show_reason_close()
{
	int k = check_close();
	if (k == 1)
		cout << "The zoo closed because the zoo keeper had enough of cleaning and quit!" << endl;
	if (k == 2)
		cout << "The zoo closed because the seller ran out of peanuts." << endl;
	if (k == 3)
		cout << "The zoo closed because the seller ran out of carrots." << endl;
	if (k == 4)
		cout << "The zoo closed because the seller ran out of bananas." << endl;

};

void Zoo::seller_money()
{
	cout << "The seller has made " << seller.return_money() << " dollors" << endl;
};


void Zoo::showall()
{
     show_days_open();	
	 show_reason_close();
	 show_totnumber();
	 seller_money();
	 if (on_day != 1)
	 {
		 cout << "The elephant enclosure was closed for " << closeday[0] << " days ." << endl;
		 cout << "The giraffe1 enclosure was closed for " << closeday[1] << " days ." << endl;
		 cout << "The giraffe2 enclosure was closed for " << closeday[2] << " days ." << endl;
		 cout << "The monkey1 enclosure was closed for " << closeday[3] << " days ." << endl;
		 cout << "The monkey2 enclosure was closed for " << closeday[4] << " days ." << endl;
		 cout << "The monkey3 enclosure was closed for " << closeday[5] << " days ." << endl;
	 }
}
void Zoo::dayover()
{
	delete[]adult;

}